package ex3.render.raytrace;

import java.util.Map;
import math.*;

public class CameraObject
{
	protected Point3D eyeDirection;
    private Vec direction;
    private double windowWidth;
    private double distance;
    private Vec up;
    private Vec right;
    private Vec accurateUp;

    public CameraObject()
    {
    }

    public void init(@SuppressWarnings("rawtypes") Map attributes)
    {
        if(attributes.containsKey("eye"))
            eyeDirection = new Point3D((String)attributes.get("eye"));
        if(attributes.containsKey("direction"))
        {
            direction = new Vec((String)attributes.get("direction"));
            direction.normalize();
        }
        if(attributes.containsKey("look-at"))
        {
            Point3D lookAt = new Point3D((String)attributes.get("look-at"));
            direction = Point3D.sub(lookAt, eyeDirection);
            direction.normalize();
        }
        if(attributes.containsKey("screen-width"))
            windowWidth = Double.parseDouble((String)attributes.get("screen-width"));
        if(attributes.containsKey("screen-dist"))
            distance = Double.parseDouble((String)attributes.get("screen-dist"));
        if(attributes.containsKey("up-direction"))
            up = new Vec((String)attributes.get("up-direction"));
        right = Vec.crossProd(direction, up);
        right.normalize();
        accurateUp = Vec.crossProd(right, direction);
        accurateUp.normalize();
    }

    public Ray buildRay(double x, double y, double height, double width)
    {
        double ratio = windowWidth / width;
        double moveUp = -(y - height / 2D) * ratio;
        double moveRight = (x - width / 2D) * ratio;
        Vec accomulatedDirection = Vec.add(Point3D.sub(eyeDirection, new Point3D(0.0D, 0.0D, 0.0D)), Vec.scale(distance, direction));
        accomulatedDirection.add(Vec.add(Vec.scale(moveUp, accurateUp), Vec.scale(moveRight, right)));
        accomulatedDirection.sub(Point3D.sub(eyeDirection, new Point3D(0.0D, 0.0D, 0.0D)));
        accomulatedDirection.normalize();
        return new Ray(eyeDirection, accomulatedDirection);
    }
}